package com.obas.business.analogy.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.springframework.jdbc.core.simple.ParameterizedSingleColumnRowMapper;

import com.ease.common.vo.MapParameter;
import com.ease.dao.jdbctemplate.rowmapper.ParameterizedBeanPropertyRowMapper;
import com.ease.platform.access.service.impl.AbstractNamespaceJdbcTemplateAccessServiceImpl;
import com.obas.access.business.service.CustomerAccessService;
import com.obas.access.business.service.CustomerNetworkServingAccessService;
import com.obas.access.mature.service.BusinessApplicationAccessService;
import com.obas.access.metadata.service.IndicatorTypeAccessService;
import com.obas.business.analogy.service.AnalogyManagementService;
import com.obas.business.analogy.util.AnalogyTableNameUtil;
import com.obas.business.analogy.vo.AnalogyParam;
import com.obas.business.analogy.vo.CustomerContextObject;
import com.obas.business.analogy.vo.UserBusinessExperienceUser;
import com.obas.business.analogy.vo.UserNetworkExperienceIndicator;
import com.obas.business.analogy.vo.UserNetworkExperienceUser;
import com.obas.model.business.Customer;
import com.obas.model.business.CustomerNetworkServing;
import com.obas.model.intermediate.UserAppKqiAggObject;
import com.obas.model.mature.BusinessApplication;
import com.obas.model.metadata.IndicatorType;
import com.obas.model.type.AnalogyDimensionType;
import com.obas.model.type.ProcessDimensionType;
import com.obas.model.type.TimeDimensionType;
import com.obas.model.type.util.ValueRankTypeUtil;

public class AnalogyManagementServiceImpl extends AbstractNamespaceJdbcTemplateAccessServiceImpl implements AnalogyManagementService {

	private IndicatorTypeAccessService indicatorTypeAccessService;

	private CustomerAccessService customerAccessService;

	private CustomerNetworkServingAccessService customerNetworkServingAccessService;

	private BusinessApplicationAccessService businessApplicationAccessService;

	public CustomerContextObject findCustomerContextObject(AnalogyParam analogyParam) {
		CustomerContextObject customerContextObject = new CustomerContextObject();
		customerContextObject.setCustomerId(analogyParam.getCustomerId());
		customerContextObject.setNetworkServingId(analogyParam.getNetworkServingId());

		Customer customer = customerAccessService.findById(analogyParam.getCustomerId());
		customerContextObject.setCustomer(customer);

		CustomerNetworkServing customerNetworkServing = customerNetworkServingAccessService.findByCustomerIdNetworkServingId(analogyParam.getCustomerId(), analogyParam.getNetworkServingId());
		customerContextObject.setCustomerNetworkServing(customerNetworkServing);

		return customerContextObject;
	}

	public List<UserAppKqiAggObject> findUserBusinessExperienceIndicatorGrid(AnalogyParam analogyParam) {

		MapParameter parameter = new MapParameter();
		//
		String timeDimensionTypeCode = analogyParam.getTimeDimensionTypeCode();
		TimeDimensionType timeDimensionType = TimeDimensionType.get(timeDimensionTypeCode);

		//
		parameter.put("timeDimensionTypeCode", timeDimensionType.getCode());

		List<Map<String, Object>> batchTimestamps = this.getJdbcTemplateDataAccessObject().find(statement("findLastBatchTimestamp"), parameter);
		Date batchTimestamp = (Date) (batchTimestamps.get(0).get("BATCHTIMESTAMP"));

		//
		parameter.put("batchTimestamp", batchTimestamp);

		//
		String indicatorTypeCode = analogyParam.getIndicatorTypeCode();
		IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
		parameter.put("indicatorTypeId", indicatorType.getId());

		//
		AnalogyDimensionType analogyDimensionType = AnalogyDimensionType.USERAPP;
		String tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType, ProcessDimensionType.KQI_AGG);
		parameter.put("tableName", tableName);

		//
		List<UserAppKqiAggObject> userAppKqiAggObjects = this.getJdbcTemplateDataAccessObject().find(statement("findUserAppGrid", parameter), parameter,
				ParameterizedBeanPropertyRowMapper.newInstance(UserAppKqiAggObject.class));

		if (null != userAppKqiAggObjects) {
			Map<Long, Customer> customers = new HashMap<Long, Customer>();
			Customer customer = null;

			Map<Long, BusinessApplication> businessApplications = new HashMap<Long, BusinessApplication>();
			BusinessApplication businessApplication = null;

			for (UserAppKqiAggObject userAppKqiAggObject : userAppKqiAggObjects) {

				userAppKqiAggObject.setIndicatorTypeName(indicatorType.getName());
				//
				userAppKqiAggObject.setRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getValue(), userAppKqiAggObject.getRank()));
				userAppKqiAggObject.setSameBandwidthRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBandwidthRank()));
				userAppKqiAggObject.setSameBrasRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasRank()));
				userAppKqiAggObject.setSameBrasPortRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasPortRank()));
				userAppKqiAggObject.setSameSvlanRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameSvlanRank()));
				userAppKqiAggObject.setSameOnuRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameOnuRank()));
				//
				long appIdentity = userAppKqiAggObject.getAppIdentity();
				businessApplication = businessApplications.get(appIdentity);
				if (null == businessApplication) {
					businessApplication = businessApplicationAccessService.findByIdentity(appIdentity);
					businessApplications.put(appIdentity, businessApplication);
				}
				if (null != businessApplication) {
					userAppKqiAggObject.setAppName(businessApplication.getName());
				}
				//
				customer = customers.get(userAppKqiAggObject.getCustomerId());
				if (null == customer) {
					customer = customerAccessService.findById(userAppKqiAggObject.getCustomerId());
					customers.put(userAppKqiAggObject.getCustomerId(), customer);
				}
				userAppKqiAggObject.setCustomerUsername(customer.getUsername());
			}
		}

		return userAppKqiAggObjects;
	}

	public List<UserBusinessExperienceUser> findUserBusinessExperienceUserGrid(AnalogyParam analogyParam) {


		MapParameter parameter = new MapParameter();
		//
		String timeDimensionTypeCode = analogyParam.getTimeDimensionTypeCode();
		TimeDimensionType timeDimensionType = TimeDimensionType.get(timeDimensionTypeCode);

		//
		parameter.put("timeDimensionTypeCode", timeDimensionType.getCode());

		List<Map<String, Object>> batchTimestamps = this.getJdbcTemplateDataAccessObject().find(statement("findLastBatchTimestamp"), parameter);
		Date batchTimestamp = (Date) (batchTimestamps.get(0).get("BATCHTIMESTAMP"));

		//
		parameter.put("batchTimestamp", batchTimestamp);
		
		//
		AnalogyDimensionType analogyDimensionType = AnalogyDimensionType.USERAPP;
		String tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType, ProcessDimensionType.KQI_AGG);
		parameter.put("tableName", tableName);

		Map<Long, Integer> customerIdRanks = new HashMap<Long, Integer>();

		for (String indicatorTypeCode : new String[] { "V2", "V3" }) {

			//
			IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
			parameter.put("indicatorTypeId", indicatorType.getId());

			//
			List<Long> customerIds = this.getJdbcTemplateDataAccessObject().find(statement("findUserWorseByIndicatorTypeId", parameter), parameter,
					ParameterizedSingleColumnRowMapper.newInstance(Long.class));
			if (null != customerIds) {
				for (long customerId : customerIds) {
					Integer rank = customerIdRanks.get(customerId);
					if (null == rank) {
						customerIdRanks.put(customerId, 1);
					} else {
						customerIdRanks.put(customerId, ++rank);
					}
				}
			}
		}

		List<Long> customerIds = new ArrayList<Long>();
		Iterator<Map.Entry<Long, Integer>> iterator = customerIdRanks.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<Long, Integer> entry = iterator.next();
			if (entry.getValue() >= 2) {
				customerIds.add(entry.getKey());
			}
		}
		parameter.put("customerIds", customerIds);

		{
		analogyDimensionType = AnalogyDimensionType.USERAPP;
		tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType, ProcessDimensionType.KQI_AGG);
		parameter.put("tableName", tableName);
		}
		
		List<UserBusinessExperienceUser> userBusinessExperienceUsers = this.getJdbcTemplateDataAccessObject().find(statement("findUserBusinessExperienceUserGrid", parameter), parameter,
				ParameterizedBeanPropertyRowMapper.newInstance(UserBusinessExperienceUser.class));
		if (null == userBusinessExperienceUsers) {
			return null;
		}

		
		Map<Long, BusinessApplication> businessApplications = new HashMap<Long, BusinessApplication>();
		BusinessApplication businessApplication = null;
		
		Map<Long, Customer> customers = new HashMap<Long, Customer>();
		Customer customer = null;
		for (UserBusinessExperienceUser userBusinessExperienceUser : userBusinessExperienceUsers) {

			userBusinessExperienceUser.setV2RankText(ValueRankTypeUtil.text(userBusinessExperienceUser.getV2Rank()));
			userBusinessExperienceUser.setV3RankText(ValueRankTypeUtil.text(userBusinessExperienceUser.getV2Rank()));

			
			 long appIdentity = userBusinessExperienceUser.getAppIdentity();
			 businessApplication = businessApplications.get(appIdentity);
			 if (null == businessApplication) {
			 businessApplication = businessApplicationAccessService.findByIdentity(appIdentity);
			 businessApplications.put(appIdentity, businessApplication);
			 }
			 if (null != businessApplication) {
				 userBusinessExperienceUser.setAppName(businessApplication.getName());
			 }
			
			
			//
			long customerId = userBusinessExperienceUser.getCustomerId();
			customer = customers.get(customerId);
			if (null == customer) {
				customer = customerAccessService.findById(customerId);
				customers.put(customerId, customer);
			}
			userBusinessExperienceUser.setCustomerUsername(customer.getUsername());
		}
		return userBusinessExperienceUsers;

	}

	

	public List<UserAppKqiAggObject> findUserNetworkExperienceIndicatorGrid(AnalogyParam analogyParam) {


		MapParameter parameter = new MapParameter();
		//
		String timeDimensionTypeCode = analogyParam.getTimeDimensionTypeCode();
		TimeDimensionType timeDimensionType = TimeDimensionType.get(timeDimensionTypeCode);

		//
		parameter.put("timeDimensionTypeCode", timeDimensionType.getCode());

		List<Map<String, Object>> batchTimestamps = this.getJdbcTemplateDataAccessObject().find(statement("findLastBatchTimestamp"), parameter);
		Date batchTimestamp = (Date) (batchTimestamps.get(0).get("BATCHTIMESTAMP"));

		//
		parameter.put("batchTimestamp", batchTimestamp);

		//
		String indicatorTypeCode = analogyParam.getIndicatorTypeCode();
		IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
		parameter.put("indicatorTypeId", indicatorType.getId());

		//
		AnalogyDimensionType analogyDimensionType = AnalogyDimensionType.USER;
		String tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType, ProcessDimensionType.KQI_AGG);
		parameter.put("tableName", tableName);

		//
		List<UserAppKqiAggObject> userAppKqiAggObjects = this.getJdbcTemplateDataAccessObject().find(statement("findUserNetworkExperienceIndicatorGrid", parameter), parameter,
				ParameterizedBeanPropertyRowMapper.newInstance(UserAppKqiAggObject.class));

		if (null != userAppKqiAggObjects) {
			Map<Long, Customer> customers = new HashMap<Long, Customer>();
			Customer customer = null;

			Map<Long, BusinessApplication> businessApplications = new HashMap<Long, BusinessApplication>();
			BusinessApplication businessApplication = null;

			for (UserAppKqiAggObject userAppKqiAggObject : userAppKqiAggObjects) {

				userAppKqiAggObject.setIndicatorTypeName(indicatorType.getName());
				//
				userAppKqiAggObject.setRouteRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getRouteRank()));
				userAppKqiAggObject.setSameBandwidthRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBandwidthRank()));
				userAppKqiAggObject.setSameBrasRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasRank()));
				userAppKqiAggObject.setSameBrasPortRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasPortRank()));
				userAppKqiAggObject.setSameSvlanRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameSvlanRank()));
				userAppKqiAggObject.setSameOnuRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameOnuRank()));
				//
				long appIdentity = userAppKqiAggObject.getAppIdentity();
				businessApplication = businessApplications.get(appIdentity);
				if (null == businessApplication) {
					businessApplication = businessApplicationAccessService.findByIdentity(appIdentity);
					businessApplications.put(appIdentity, businessApplication);
				}
				if (null != businessApplication) {
					userAppKqiAggObject.setAppName(businessApplication.getName());
				}
				//
				customer = customers.get(userAppKqiAggObject.getCustomerId());
				if (null == customer) {
					customer = customerAccessService.findById(userAppKqiAggObject.getCustomerId());
					customers.put(userAppKqiAggObject.getCustomerId(), customer);
				}
				userAppKqiAggObject.setCustomerUsername(customer.getUsername());
			}
		}

		return userAppKqiAggObjects;
	}

	public List<UserBusinessExperienceUser> findUserNetworkExperienceUserGrid(AnalogyParam analogyParam) {


		MapParameter parameter = new MapParameter();
		//
		String timeDimensionTypeCode = analogyParam.getTimeDimensionTypeCode();
		TimeDimensionType timeDimensionType = TimeDimensionType.get(timeDimensionTypeCode);

		//
		parameter.put("timeDimensionTypeCode", timeDimensionType.getCode());

		List<Map<String, Object>> batchTimestamps = this.getJdbcTemplateDataAccessObject().find(statement("findLastBatchTimestamp"), parameter);
		Date batchTimestamp = (Date) (batchTimestamps.get(0).get("BATCHTIMESTAMP"));

		//
		parameter.put("batchTimestamp", batchTimestamp);

		AnalogyDimensionType analogyDimensionType = AnalogyDimensionType.USER;
		String tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType, ProcessDimensionType.KQI_AGG);
		parameter.put("tableName", tableName);

		Map<Long, Integer> customerIdRanks = new HashMap<Long, Integer>();

		for (String indicatorTypeCode : new String[] { "V1", "V4" }) {

			//
			IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
			parameter.put("indicatorTypeId", indicatorType.getId());

			//

			List<Long> customerIds = this.getJdbcTemplateDataAccessObject().find(statement("findUserWorseByIndicatorTypeId", parameter), parameter,
					ParameterizedSingleColumnRowMapper.newInstance(Long.class));
			if (null != customerIds) {
				for (long customerId : customerIds) {
					Integer rank = customerIdRanks.get(customerId);
					if (null == rank) {
						customerIdRanks.put(customerId, 1);
					} else {
						customerIdRanks.put(customerId, ++rank);
					}
				}
			}
		}

		List<Long> customerIds = new ArrayList<Long>();
		Iterator<Map.Entry<Long, Integer>> iterator = customerIdRanks.entrySet().iterator();
		while (iterator.hasNext()) {
			Map.Entry<Long, Integer> entry = iterator.next();
			if (entry.getValue() >= 2) {
				customerIds.add(entry.getKey());
			}
		}
		parameter.put("customerIds", customerIds);

		List<UserBusinessExperienceUser> userBusinessExperienceUsers = this.getJdbcTemplateDataAccessObject().find(statement("findUserBusinessExperienceUserGrid", parameter), parameter,
				ParameterizedBeanPropertyRowMapper.newInstance(UserBusinessExperienceUser.class));
		if (null == userBusinessExperienceUsers) {
			return null;
		}

		Map<Long, Customer> customers = new HashMap<Long, Customer>();
		Customer customer = null;
		for (UserBusinessExperienceUser userBusinessExperienceUser : userBusinessExperienceUsers) {

			userBusinessExperienceUser.setV1RankText(ValueRankTypeUtil.text(userBusinessExperienceUser.getV1Rank()));
			userBusinessExperienceUser.setV4RankText(ValueRankTypeUtil.text(userBusinessExperienceUser.getV4Rank()));

			//
			long customerId = userBusinessExperienceUser.getCustomerId();
			customer = customers.get(customerId);
			if (null == customer) {
				customer = customerAccessService.findById(customerId);
				customers.put(customerId, customer);
			}
			userBusinessExperienceUser.setCustomerUsername(customer.getUsername());
		}
		return userBusinessExperienceUsers;

	}

	public List<UserAppKqiAggObject> findUserAppHistroyRank(AnalogyParam analogyParam) {

		MapParameter parameter = new MapParameter();
		parameter.put("customerId", analogyParam.getCustomerId());
		if(analogyParam.getIndicatorTypeId()>0){
			parameter.put("indicatorTypeId", analogyParam.getIndicatorTypeId());
		} else if(notEmpty(analogyParam.getIndicatorTypeCode())) {
			String indicatorTypeCode = analogyParam.getIndicatorTypeCode();
			IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
			parameter.put("indicatorTypeId", indicatorType.getId());
		}
		parameter.put("networkServingId", analogyParam.getNetworkServingId());
		if(analogyParam.getAppIdentity()>0) {
			parameter.put("appIdentity", analogyParam.getAppIdentity());
		}
		List<UserAppKqiAggObject> userAppKqiAggObjects = this.getJdbcTemplateDataAccessObject().find(statement("findUserAppHistoryRank",parameter), parameter,
				ParameterizedBeanPropertyRowMapper.newInstance(UserAppKqiAggObject.class));

		return userAppKqiAggObjects;
	}

	// public List<UserAppKqiAggObject> findUserAppGrid(AnalogyParam analogyParam) {
	// MapParameter parameter = new MapParameter();
	// //
	// String timeDimensionTypeCode = analogyParam.getTimeDimensionTypeCode();
	// TimeDimensionType timeDimensionType = TimeDimensionType.get(timeDimensionTypeCode);
	//
	// //
	// parameter.put("timeDimensionTypeCode", timeDimensionType.getCode());
	//
	// List<Map<String, Object>> batchTimestamps =
	// this.getJdbcTemplateDataAccessObject().find(statement("findLastBatchTimestamp"), parameter);
	// Date batchTimestamp = (Date) (batchTimestamps.get(0).get("BATCHTIMESTAMP"));
	//
	// //
	// parameter.put("batchTimestamp", batchTimestamp);
	//
	// String indicatorTypeCode = analogyParam.getIndicatorTypeCode();
	// IndicatorType indicatorType = indicatorTypeAccessService.findByCode(indicatorTypeCode);
	// parameter.put("indicatorTypeId", indicatorType.getId());
	//
	// AnalogyDimensionType analogyDimensionType = AnalogyDimensionType.get(analogyParam.getAnalogyDimensionTypeCode());
	// String tableName = AnalogyTableNameUtil.tableName(analogyDimensionType, timeDimensionType,
	// ProcessDimensionType.KQI_AGG);
	// parameter.put("tableName", tableName);
	//
	// List<UserAppKqiAggObject> userAppKqiAggObjects =
	// this.getJdbcTemplateDataAccessObject().find(statement("findUserAppGrid", parameter), parameter,
	// ParameterizedBeanPropertyRowMapper.newInstance(UserAppKqiAggObject.class));
	//
	// if (null != userAppKqiAggObjects) {
	// Map<Long, Customer> customers = new HashMap<Long, Customer>();
	// Customer customer = null;
	//
	// Map<Long, BusinessApplication> businessApplications = new HashMap<Long, BusinessApplication>();
	// BusinessApplication businessApplication = null;
	//
	// for (UserAppKqiAggObject userAppKqiAggObject : userAppKqiAggObjects) {
	// userAppKqiAggObject.setRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getValue(),
	// userAppKqiAggObject.getRank()));
	// userAppKqiAggObject.setSameBandwidthRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBandwidthRank()));
	// userAppKqiAggObject.setSameBrasRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasRank()));
	// userAppKqiAggObject.setSameBrasPortRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameBrasPortRank()));
	// userAppKqiAggObject.setSameSvlanRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameSvlanRank()));
	// userAppKqiAggObject.setSameOnuRankText(ValueRankTypeUtil.text(userAppKqiAggObject.getSameOnuRank()));
	// //
	// long appIdentity = userAppKqiAggObject.getAppIdentity();
	// businessApplication = businessApplications.get(appIdentity);
	// if (null == businessApplication) {
	// businessApplication = businessApplicationAccessService.findByIdentity(appIdentity);
	// businessApplications.put(appIdentity, businessApplication);
	// }
	// if (null != businessApplication) {
	// userAppKqiAggObject.setAppName(businessApplication.getName());
	// }
	// //
	// customer = customers.get(userAppKqiAggObject.getCustomerId());
	// if (null == customer) {
	// customer = customerAccessService.findById(userAppKqiAggObject.getCustomerId());
	// customers.put(userAppKqiAggObject.getCustomerId(), customer);
	// }
	// userAppKqiAggObject.setCustomerUsername(customer.getUsername());
	// }
	// }
	//
	// return userAppKqiAggObjects;
	// }

	/**
	 * @return the indicatorTypeAccessService
	 */
	public IndicatorTypeAccessService getIndicatorTypeAccessService() {
		return indicatorTypeAccessService;
	}

	/**
	 * @param indicatorTypeAccessService
	 *            the indicatorTypeAccessService to set
	 */
	public void setIndicatorTypeAccessService(IndicatorTypeAccessService indicatorTypeAccessService) {
		this.indicatorTypeAccessService = indicatorTypeAccessService;
	}

	/**
	 * @return the customerAccessService
	 */
	public CustomerAccessService getCustomerAccessService() {
		return customerAccessService;
	}

	/**
	 * @param customerAccessService
	 *            the customerAccessService to set
	 */
	public void setCustomerAccessService(CustomerAccessService customerAccessService) {
		this.customerAccessService = customerAccessService;
	}

	/**
	 * @return the businessApplicationAccessService
	 */
	public BusinessApplicationAccessService getBusinessApplicationAccessService() {
		return businessApplicationAccessService;
	}

	/**
	 * @param businessApplicationAccessService
	 *            the businessApplicationAccessService to set
	 */
	public void setBusinessApplicationAccessService(BusinessApplicationAccessService businessApplicationAccessService) {
		this.businessApplicationAccessService = businessApplicationAccessService;
	}

	/**
	 * @return the customerNetworkServingAccessService
	 */
	public CustomerNetworkServingAccessService getCustomerNetworkServingAccessService() {
		return customerNetworkServingAccessService;
	}

	/**
	 * @param customerNetworkServingAccessService
	 *            the customerNetworkServingAccessService to set
	 */
	public void setCustomerNetworkServingAccessService(CustomerNetworkServingAccessService customerNetworkServingAccessService) {
		this.customerNetworkServingAccessService = customerNetworkServingAccessService;
	}

}
